package cn.lin.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.apache.poi.xslf.usermodel.*;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author hx
 * @date 2024/12/3 21:21
 */
public class PPTUtil {

    /**
     * 将后缀为.pptx的PPT转换为图片
     */
    public static List<String> ppt2Png(String filePath) {
        List<String> urls = new ArrayList<>();

        String objectName = filePath.substring(filePath.lastIndexOf(".com/") + 5);
        System.out.println(objectName);
        OSS ossClient = null;

        InputStream is = null;
        try {
            ossClient = new OSSClientBuilder().build(OSSUtil.endpoint, OSSUtil.accessKeyId, OSSUtil.accessKeySecret);
            is = ossClient.getObject(OSSUtil.bucketName,objectName).getObjectContent();

            XMLSlideShow xmlSlideShow = new XMLSlideShow(is);
            // 获取大小
            Dimension pgsize = xmlSlideShow.getPageSize();
            // 获取幻灯片
            List<XSLFSlide> slides = xmlSlideShow.getSlides();

            // 定义缩放比例（例如，2倍）
            double scale = 2.0;

            // 计算新的宽度和高度
            int newWidth = (int) (pgsize.width * scale);
            int newHeight = (int) (pgsize.height * scale);

            // 设置DPI
            int dpi = 400;
            float dotsPerMillimeter = dpi / 25.4f;

            for (int i = 0; i < slides.size(); i++) {
                // 解决乱码问题

                // 根据原始大小生成图片
                BufferedImage img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphics = img.createGraphics();

                //设置图片参数
                setupGraphics(graphics,scale,newWidth,newHeight);

                // 绘制幻灯片内容
                slides.get(i).draw(graphics);
                graphics.dispose();

                // 使用ImageWriter和IIOMetadata设置DPI
                Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
                if (!writers.hasNext()) {
                    throw new IllegalStateException("No JPEG writer found");
                }
                ImageWriter writer = writers.next();
                ImageWriteParam param = writer.getDefaultWriteParam();

                IIOMetadata metadata = writer.getDefaultImageMetadata(new javax.imageio.ImageTypeSpecifier(img), param);
                if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
                    throw new IllegalStateException("Cannot write metadata");
                }

                setDPI(metadata, dotsPerMillimeter);

                // 将图像写入字节数组输出流
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
                writer.setOutput(ios);
                writer.write(null, new javax.imageio.IIOImage(img, null, metadata), param);
                ios.close();
                writer.dispose();
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

                // Upload image to OSS and get URL
                String fileName = (i + 1) + ".jpg";
                String imageUrl = OSSUtil.upload(fileName, bais);
                urls.add(imageUrl);
                writer.dispose();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("图片转换异常");
        } finally {
            if(ossClient != null){
                ossClient.shutdown();
            }
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return urls;
    }

    /**
     * @description: 配置Graphics对象以确保高质量渲染
     * @author: hx
     * @date:  2024/12/3 22:40
     * @param scale
     * @param width
     * @param height
     **/
    public static void setupGraphics(Graphics2D graphics,double scale,int width,int height){
        // 设置高质量的渲染提示
        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 设置背景颜色
        graphics.setPaint(Color.white);
        graphics.fill(new Rectangle2D.Float(0, 0, width, height));
        // 缩放绘制
        AffineTransform at = new AffineTransform();
        at.scale(scale, scale);
        graphics.transform(at);
    }

    /**
     * @description: 处理乱码问题
     * @author: hx
     * @date:  2024/12/3 22:45
     * @param: slide
     **/
    private static void setFontForShapes(XSLFSlide slide) {
        List<XSLFShape> shapes = slide.getShapes();
        for (XSLFShape shape : shapes) {
            if (shape instanceof XSLFTextShape) {
                XSLFTextShape textShape = (XSLFTextShape) shape;
                List<XSLFTextParagraph> paragraphs = textShape.getTextParagraphs();
                for (XSLFTextParagraph paragraph : paragraphs) {
                    for (XSLFTextRun run : paragraph.getTextRuns()) {
                        run.setFontFamily("宋体");
                    }
                }
            }
        }
    }

    /**
     * 设置图片的DPI
     */
    private static void setDPI(IIOMetadata metadata, float dotsPerMillimeter) throws Exception {
        String formatName = "javax_imageio_jpeg_image_1.0";
        Node tree = metadata.getAsTree(formatName);

        NodeList appSegments = ((Element) tree).getElementsByTagName("app0JFIF");
        Element jfifSegment = (Element) appSegments.item(0);

        if (jfifSegment != null) {
            jfifSegment.setAttribute("Xdensity", Integer.toString(Math.round(dotsPerMillimeter)));
            jfifSegment.setAttribute("Ydensity", Integer.toString(Math.round(dotsPerMillimeter)));
            // 1 means dots per inch
            jfifSegment.setAttribute("resUnits", "1");
        }

        metadata.setFromTree(formatName, tree);
    }
}
